﻿using System;

namespace NHibernate.Sidekick.Data.Domain
{
    /// <summary>
    /// Reference type for the DomainObject.
    /// </summary>
    public interface IDomainObject<TId>
    {
        /// <summary>
        /// The object's identifier.
        /// </summary>
        TId Id { get;  }
    }

    /// <summary>
    /// Conceptual model of the specified entity.
    /// </summary>
    /// <typeparam name="T">The type of domain object</typeparam>
    /// <typeparam name="TId">The type of the identifier.</typeparam>
    [Serializable]
    public abstract class DomainObject<T, TId> : IDomainObject<TId> where T : class 
    {
        /// <summary>
        /// The object's identifier.
        /// </summary>
        public virtual TId Id { get; set; }

        #region Equality by Id
        public override bool Equals(object obj)
        {
            return base.Equals(obj);
        }

        public virtual bool Equals(DomainObject<T, TId> other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Equals(other.Id, Id);
        }

        public override int GetHashCode()
        {
            return Id.GetHashCode();
        }

        public static bool operator ==(DomainObject<T, TId> left, DomainObject<T, TId> right)
        {
            return Equals(left, right);
        }

        public static bool operator !=(DomainObject<T, TId> left, DomainObject<T, TId> right)
        {
            return !Equals(left, right);
        } 
        #endregion
    }
}